package com.fblinux.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class EncryptPhoneNumber extends GenericUDF {

    // 初始化方法，在真正执行计算之前会调用一次
    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {

        if(arguments.length!=1){
            throw new UDFArgumentException("只能接收一个参数");
        }

        ObjectInspector argument = arguments[0];
        if(argument.getCategory()!=ObjectInspector.Category.PRIMITIVE){
            throw new UDFArgumentException("只能接收基本数据类型的参数");
        }

        PrimitiveObjectInspector primitiveObjectInspector = (PrimitiveObjectInspector) argument;
        if(primitiveObjectInspector.getPrimitiveCategory()!=PrimitiveObjectInspector.PrimitiveCategory.STRING){
            throw new UDFArgumentException("只能接收STRING类型的参数");
        }

        return PrimitiveObjectInspectorFactory.javaStringObjectInspector;
    }

    // 每行数据调用一下这个方法，数据的计算逻辑主要在这里实现
    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        DeferredObject argument = arguments[0];
        if (argument.get() != null) {
            String phone = argument.get().toString();
            //判断手机号是否为11位
            if (phone.length() == 11) {
                //判断数据是否满足中国大陆手机号码规范
                String regex = "^(1[3-9]\\d{9}$)";
                Pattern p = Pattern.compile(regex);
                Matcher m = p.matcher(phone);
                if (m.matches()) {
                    //进入这里都是符合手机号规则的
                    StringBuilder sb = new StringBuilder(phone);
                    sb.replace(3, 7, "xxxx");
                    return sb;
                } else {
                    //不符合手机号规则 数据直接原封不动返回
                    return phone;
                }
            } else {
                return phone;
            }
        }else{
            return null;
        }
    }

    // 自定义函数如果要在执行计划里面进行展示，就在这里定义要展示的内容，通常自定义函数没有展示需求
    @Override
    public String getDisplayString(String[] children) {
        return "这是hive自定义函数，实现手机号脱敏功能";
    }
}

